﻿using IServices;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using YL.Core.Entity;
using YL.Core.Entity.Meter;

namespace RocketMQHandler
{
    public class DeviceEnergyDataWorker
    {
        private readonly IMeter_DeviceEnergyLogService deviceEnergyLogService;
        private readonly IMeter_DeviceDataServices deviceDataServices;
        private readonly IMeter_DeviceEnergyDayServices deviceEnergyDayServices;
        private readonly IMeter_DeviceEnergyMonthServices deviceEnergyMonthServices;
        private readonly IMeter_DeviceInfoServices deviceInfoServices;

        public DeviceEnergyDataWorker(IMeter_DeviceEnergyLogService DeviceEnergyLogService,
                                      IMeter_DeviceDataServices DeviceDataServices,
                                      IMeter_DeviceEnergyDayServices DeviceEnergyDayServices,
                                      IMeter_DeviceEnergyMonthServices DeviceEnergyMonthServices,
                                      IMeter_DeviceInfoServices DeviceInfoServices)
        {
            deviceEnergyLogService = DeviceEnergyLogService;
            deviceDataServices = DeviceDataServices;
            deviceEnergyDayServices = DeviceEnergyDayServices;
            deviceEnergyMonthServices = DeviceEnergyMonthServices;
            deviceInfoServices = DeviceInfoServices;
            StartTask();
        }

        public void StartTask()
        {
            Thread dailyTask = new Thread(CycDailyCalTask);
            dailyTask.IsBackground = true;
            dailyTask.Start();

            Thread monthTask = new Thread(CycMonthCalTask);
            monthTask.IsBackground = true;
            monthTask.Start();
        }
        /// <summary>
        /// 增加新的能耗记录
        /// </summary>
        /// <param name="iotId"></param>
        /// <param name="deviceName"></param>
        /// <param name="value"></param>
        public void InsertNewEnergyLog(string iotId,string deviceName,decimal value)
        {
            DeviceEnergyLog log = new DeviceEnergyLog();
            log.device_code = deviceName;
            log.device_name = iotId;
            log.insert_time = DateTime.Now;
            log.power_value = value;
            deviceEnergyLogService.Insert(log);
        }

        /// <summary>
        /// 日数据周期计算
        /// </summary>
        private void CycDailyCalTask()
        {
            DateTime datetimeNow;

            while (true)
            {
                datetimeNow = DateTime.Now;
                List<DeviceInfo> deviceList = deviceInfoServices.QueryableToList(x=>x.DeviceId>0);
                foreach (var item in deviceList)
                {
                    CheckLastDailyData(item, datetimeNow);//检查上一天的数据是否结算
                    CalDailyData(item, datetimeNow);      //定期结算天数据
                }
                deviceEnergyLogService.Delete(x=>x.insert_time<= datetimeNow.AddDays(-30));//删除30天前记录
                Thread.Sleep(6000 * 10*6);//60*10*6=60分钟计算一次
            }
        }
        /// <summary>
        /// 月数据周期计算
        /// </summary>
        private void CycMonthCalTask()
        {
            DateTime datetimeNow;
            int hour12 = 6000 * 10 * 6 * 12;
            while (true)
            {
                datetimeNow = DateTime.Now;
                List<DeviceInfo> deviceList = deviceInfoServices.QueryableToList(x => x.DeviceId > 0);
                foreach (var item in deviceList)
                {
                    CheckLastMonthData(item, datetimeNow);//检查上一天的数据是否结算
                    CalMonthData(item, datetimeNow);      //定期结算天数据
                }
                
                Thread.Sleep(hour12);//60*10*6=60*12 12小时计算一次
            }
        }
        /// <summary>
        /// 计算天数据
        /// </summary>
        /// <param name="device">电耗对象</param>
        /// <param name="CalTime">计算的时刻点</param>
        private void CalDailyData(DeviceInfo device, DateTime CalTime)
        {
            DeviceEnergyDay dailyItem = new DeviceEnergyDay();
            DateTime stTime, edTime;

            stTime = CalTime.Date;//一天的开始时间
            edTime = CalTime.Date.AddHours(24);//一天的结束时间

            var powerValue = deviceEnergyDayServices.QueryDevicePoweData(stTime, edTime, device.AliDeviceName);
            
            dailyItem = deviceEnergyDayServices.Queryable().First(x => x.DeviceId == device.DeviceId && x.Date == stTime);
            if (dailyItem != null)//已经存在,则更新
            {
                dailyItem.EnergyEnd = (double)powerValue.Item3;//期末结算
                dailyItem.EnergyCost = (double)powerValue.Item1;
                dailyItem.LastTime = DateTime.Now;
                deviceEnergyDayServices.UpdateEntity(dailyItem);
            }
            else
            {
                dailyItem = new DeviceEnergyDay();
                dailyItem.EnergyStart = (double)powerValue.Item2;
                dailyItem.EnergyEnd = (double)powerValue.Item3;
                dailyItem.EnergyCost = (double)powerValue.Item1;
                dailyItem.DeviceId = device.DeviceId;
                dailyItem.LastTime = CalTime;
                dailyItem.Date = CalTime;
                deviceEnergyDayServices.Insert(dailyItem);
            }
        }
        /// <summary>
        /// 检查上一天的数据是否结算。
        /// 用last_time去比较insert_time.last_time更新的值应该是第二天的记录
        /// </summary>
        /// <param name="powerItem"></param>
        /// <param name="datetimeNow">系统当前的时间点</param>
        private void CheckLastDailyData(DeviceInfo device, DateTime datetimeNow)
        {
            DeviceEnergyDay dailyItem = new DeviceEnergyDay();
            DateTime LastDays = datetimeNow.AddDays(-1);
            //查找上一天的数据
            dailyItem = deviceEnergyDayServices.Queryable()
                                               .First(x => x.DeviceId == device.DeviceId && x.Date == LastDays.Date);
            if (dailyItem != null)
            {
                if (dailyItem.LastTime.Date == dailyItem.Date)//last_time与date相等
                {
                    CalDailyData(device, LastDays);
                }
            }
        }
        /// <summary>
        /// 检查上一天的数据是否结算。
        /// 用last_time去比较insert_time.last_time更新的值应该是第二天的记录
        /// </summary>
        /// <param name="powerItem"></param>
        /// <param name="datetimeNow">系统当前的时间点</param>
        private void CheckLastMonthData(DeviceInfo device, DateTime datetimeNow)
        {
            DeviceEnergyMonth monthItem = new DeviceEnergyMonth();
            DateTime LastMonths = datetimeNow.AddMonths(-1);
            //查找上一个月的数据
            monthItem = deviceEnergyMonthServices.Queryable()
                                                 .First(x => x.DeviceId == device.DeviceId && x.Date == LastMonths.Date);
            if (monthItem != null)
            {
                if (monthItem.LastTime.Date == monthItem.Date)//last_time与date相等,说明还未完全结算
                {
                    CalMonthData(device, LastMonths);
                }
            }
        }

        /// <summary>
        /// 计算月数据
        /// </summary>
        /// <param name="device">电耗对象</param>
        /// <param name="CalTime">计算的时刻点</param>
        private void CalMonthData(DeviceInfo device, DateTime CalTime)
        {
            DeviceEnergyMonth monthItem = new DeviceEnergyMonth();
            DateTime stTime, edTime;

            stTime = DateTime.Now.AddDays(1 - DateTime.Now.Day).Date;//当月的第一天
            edTime = DateTime.Now.AddDays(1 - DateTime.Now.Day).Date.AddMonths(1).AddSeconds(-1);//当月最后一天

            var res = deviceEnergyMonthServices.GetDevicePoweData(stTime, edTime, device.AliDeviceName);

            monthItem = deviceEnergyMonthServices.Queryable().First(x => x.DeviceId == device.DeviceId && x.Date == stTime);
            if (monthItem != null)//已经存在,则更新
            {
                monthItem.EnergyEnd = (double)res.Item3;//期末结算
                monthItem.EnergyCost = (double)res.Item1;
                monthItem.LastTime = DateTime.Now;
                deviceEnergyMonthServices.UpdateEntity(monthItem);
            }
            else
            {
                monthItem = new DeviceEnergyMonth();
                monthItem.EnergyStart = (double)res.Item2;
                monthItem.EnergyEnd = (double)res.Item3;
                monthItem.EnergyCost = (double)res.Item1;
                monthItem.DeviceId = device.DeviceId;
                monthItem.LastTime = CalTime;
                monthItem.Date = CalTime;
                deviceEnergyMonthServices.Insert(monthItem);
            }
        }

    }
}
